home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / 3DTOSHI2.ZIP / mpg3d / source / G3ddraw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  66.0 KB  |  2,090 lines

  1.  
  2. // g3ddraw.cpp
  3. //
  4. // Copyright (c) 1996 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgfx.h"
  7. #include "g3ddraw.h"
  8. #include "lg3dras.h"
  9. #include "math.h"
  10. #if defined (__FORWATCOM__)
  11.   #include "lg3d256.h"
  12. #endif
  13.  
  14. #define CLIP_TOP    (LONG)(1<<0)
  15. #define CLIP_LEFT   (LONG)(1<<1)
  16. #define CLIP_BOTTOM (LONG)(1<<2)
  17. #define CLIP_RIGHT  (LONG)(1<<3)
  18.  
  19. LONG FXPMult ( LONG Val1, LONG MulBy );
  20. #pragma aux FXPMult = \
  21.   "imul EDX" \
  22.   "shrd EAX, EDX, 16" \
  23.   parm [EAX] [EDX] \
  24.   value [EAX];
  25.  
  26. LONG FXPDiv ( LONG Val1, LONG DivBy );
  27. #pragma aux FXPDiv = \
  28.   "cdq" \
  29.   "shld EDX, EAX, 16" \
  30.   "sal  EAX, 16" \
  31.   "idiv EBX" \
  32.   parm [EAX] [EBX] \
  33.   modify [EDX] \
  34.   value [EAX];
  35.  
  36. LONG FXPMultDiv ( LONG Val1, LONG MulBy, LONG DivBy );
  37. #pragma aux FXPMultDiv = \
  38.   "imul EDX" \
  39.   "idiv EBX" \
  40.   parm [EAX] [EDX] [EBX] \
  41.   value [EAX];
  42.  
  43. //*****************************************************
  44. //
  45. // G3D Drawing Driver
  46. //
  47. //*****************************************************
  48.  
  49. FLPEDGE *FLPEdge1 = NULL;
  50. FLPEDGE *FLPEdge2 = NULL;
  51. FLPEDGETABLE *FLPEdgeTable = NULL;
  52.  
  53. FXPEDGE *FXPEdge1 = NULL;
  54. FXPEDGE *FXPEdge2 = NULL;
  55. FXPEDGETABLE FXPEdgeTable;
  56.  
  57. FXPPOINT2D TopClipPoly[8];
  58. FXPPOINT2D LeftClipPoly[8];
  59. FXPPOINT2D BottomClipPoly[8];
  60. FXPPOINT2D RightClipPoly[8];
  61. FXPPOINT2D *ClipPoly = NULL;
  62.  
  63. float *DivTable = NULL; ;
  64.  
  65. G3DDRAW::G3DDRAW ()
  66.   {
  67.     ShadeFlags = SHADE_GOURAUD;
  68.     FaceFlags = FACE_TEXTURE;
  69.     Dest = NULL;
  70.     ShadeTable = NULL;
  71.     CenterX = 160;
  72.     CenterY = 100;
  73.     ViewDistance = (float)100;
  74.     ViewPort.x1 = (LONG)0;
  75.     ViewPort.y1 = (LONG)0;
  76.     ViewPort.x2 = (LONG)319;
  77.     ViewPort.y2 = (LONG)199;
  78.     MIN_Z_DISTANCE = (float)10.0;
  79.     DoHaze = FALSE;
  80.  
  81.     FLPEdgeTable = new FLPEDGETABLE();
  82.     FLPEdge1 = new FLPEDGE[768];
  83.     FLPEdge2 = new FLPEDGE[768];
  84.  
  85.     FXPEdgeTable = FXPEDGETABLE();
  86.     FXPEdge1 = new FXPEDGE[768];
  87.     FXPEdge2 = new FXPEDGE[768];
  88.  
  89.     INT i;
  90.  
  91.     DivTable = new float [30000];
  92.     DivTable[0] = (float)0; 
  93.     for (i=1;i<30000;i++)
  94.       {
  95.         DivTable[i] = (float)1/i;  
  96.       } // End for
  97.  
  98.     InitFunctionTable ();
  99.   } // End of Constructor for G3DDRAW
  100.  
  101. G3DDRAW::~G3DDRAW ()
  102.   {
  103.     if (FLPEdge1!=NULL)
  104.       delete FLPEdge1;
  105.     FLPEdge1 = NULL;
  106.  
  107.     if (FLPEdge2!=NULL)
  108.       delete FLPEdge2;
  109.     FLPEdge2 = NULL;
  110.  
  111.     if (FLPEdgeTable!=NULL)
  112.       delete FLPEdgeTable;
  113.     FLPEdgeTable = NULL;
  114.  
  115.     if (FXPEdge1!=NULL)
  116.       delete FXPEdge1;
  117.     FXPEdge1 = NULL;
  118.  
  119.     if (FXPEdge2!=NULL)
  120.       delete FXPEdge2;
  121.     FXPEdge2 = NULL;
  122.  
  123.     if (DivTable!=NULL)
  124.       delete DivTable;
  125.     DivTable = NULL;
  126.   } // End of Destructor for G3DDRAW
  127.       
  128. VOID G3DDRAW::SetDestination ( IMAGE *Destination )
  129.   {
  130.     Dest = Destination;
  131.     if (Dest!=NULL)
  132.       ViewPort = Dest->GetViewPort ();
  133.   } // End of SetDestination for G3DDRAW
  134.   
  135. VOID G3DDRAW::SetViewDistance ( float VDistance )
  136.   {
  137.     ViewDistance = VDistance;  
  138.   } // End of SetViewDistance for G3DDRAW
  139.  
  140. VOID G3DDRAW::SetScreenCenter ( LONG Cx, LONG Cy )
  141.   {
  142.     CenterX = Cx;  
  143.     CenterY = Cy;  
  144.   } // End of SetScreenCenter for G3DDRAW
  145.   
  146. VOID G3DDRAW::DrawShape ( G3DSHAPE *Shape )
  147.   {
  148.     G3DOBJECT *Object;
  149.     Object = Shape->ParentObject;
  150.     ViewPort = Dest->GetViewPort ();
  151.  
  152.     if (Object->GetObjectType()==OBJECT_TYPE_POLYHEDRON)
  153.       {
  154.         DrawPoly ( (G3DPOLYHEDRON*)Object, (G3DPOLY*)Shape );  
  155.       } // End if
  156.   } // End of DrawShape for G3DDRAW 
  157.  
  158. VOID G3DDRAW::ZIntersect ( CLIPPOINT3D *In, CLIPPOINT3D *Out, CLIPPOINT3D *Intersect,
  159.                            LONG DrawShadeFlags, LONG DrawFaceFlags )
  160.   {
  161.     float Ratio;
  162.  
  163.     Ratio = (float)(MIN_Z_DISTANCE-Out->z) / (float)(In->z-Out->z);
  164.  
  165.     Intersect->x = (In->x-Out->x)*Ratio + Out->x;
  166.     Intersect->y = (In->y-Out->y)*Ratio + Out->y;
  167.     Intersect->z = MIN_Z_DISTANCE;
  168.  
  169.     if (DrawShadeFlags==SHADE_GOURAUD)
  170.       {
  171.         Intersect->I = (In->I-Out->I)*Ratio + Out->I;  
  172.       } // End if
  173.       
  174.     if (DrawFaceFlags==FACE_TEXTURE)
  175.       {
  176.         Intersect->u = (In->u-Out->u)*Ratio + Out->u;  
  177.         Intersect->v = (In->v-Out->v)*Ratio + Out->v;  
  178.       } // End if    
  179.   } // End of ZIntersect for G3DDRAW
  180.   
  181. LONG G3DDRAW::ZClip ( CLIPPOINT3D *Points, CLIPPOINT3D *ClippedPoints,
  182.                       LONG Code, LONG DrawShadeFlags, LONG DrawFaceFlags )
  183.   {
  184.     LONG NumPoints;  
  185.     switch (Code)
  186.       {
  187.         case 1 : // z0 is behind z
  188.           ZIntersect ( &(Points[1]), &(Points[0]), &(ClippedPoints[0]), DrawShadeFlags, DrawFaceFlags );
  189.           ClippedPoints[1] = Points[1];
  190.           ClippedPoints[2] = Points[2];
  191.           ZIntersect ( &(Points[2]), &(Points[0]), &(ClippedPoints[3]), DrawShadeFlags, DrawFaceFlags );
  192.           NumPoints = 4;
  193.           break;
  194.         case 2 : // z1 is behind z
  195.           ClippedPoints[0] = Points[0];
  196.           ZIntersect ( &(Points[0]), &(Points[1]), &(ClippedPoints[1]), DrawShadeFlags, DrawFaceFlags );
  197.           ZIntersect ( &(Points[2]), &(Points[1]), &(ClippedPoints[2]), DrawShadeFlags, DrawFaceFlags );
  198.           ClippedPoints[3] = Points[2];
  199.           NumPoints = 4;
  200.           break;
  201.         case 3 : // z0 & z1 are behind z        
  202.           ZIntersect ( &(Points[2]), &(Points[1]), &(ClippedPoints[0]), DrawShadeFlags, DrawFaceFlags );
  203.           ClippedPoints[1] = Points[2];
  204.           ZIntersect ( &(Points[2]), &(Points[0]), &(ClippedPoints[2]), DrawShadeFlags, DrawFaceFlags );
  205.           NumPoints = 3;
  206.           break;
  207.         case 4 : // z2 is behind z
  208.           ClippedPoints[0] = Points[0];
  209.           ClippedPoints[1] = Points[1];
  210.           ZIntersect ( &(Points[1]), &(Points[2]), &(ClippedPoints[2]), DrawShadeFlags, DrawFaceFlags );
  211.           ZIntersect ( &(Points[0]), &(Points[2]), &(ClippedPoints[3]), DrawShadeFlags, DrawFaceFlags );
  212.           NumPoints = 4;
  213.           break;
  214.         case 5 : // z0 & z2 are behind
  215.           ZIntersect ( &(Points[1]), &(Points[0]), &(ClippedPoints[0]), DrawShadeFlags, DrawFaceFlags );
  216.           ClippedPoints[1] = Points[1];
  217.           ZIntersect ( &(Points[1]), &(Points[2]), &(ClippedPoints[2]), DrawShadeFlags, DrawFaceFlags );
  218.           NumPoints = 3;
  219.           break;
  220.         case 6 : // z1 & z2 are behind
  221.           ClippedPoints[0] = Points[0];
  222.           ZIntersect ( &(Points[0]), &(Points[1]), &(ClippedPoints[1]), DrawShadeFlags, DrawFaceFlags );
  223.           ZIntersect ( &(Points[0]), &(Points[2]), &(ClippedPoints[2]), DrawShadeFlags, DrawFaceFlags );
  224.           NumPoints = 3;
  225.           break;    
  226.       } // End switch
  227.     return NumPoints;  
  228.   } // End of ZClip for G3DDRAW
  229.  
  230. VOID G3DDRAW::DrawPoly ( G3DPOLYHEDRON *Object, G3DPOLY *Poly )
  231.   {
  232.     FXPPOINT2D Points[4];
  233.     FLPVECTOR2D *ScreenPoints;
  234.     FLPVECTOR3D *CameraPoints;
  235.     float *PointIntensities;
  236.     float *HazeValues;
  237.     DETAILDATA *DetailData;
  238.     GEOMETRYDATA *GeometryData;
  239.     LONG List0,List1,List2;
  240.     LONG DrawShadeFlags;
  241.     LONG DrawFaceFlags;
  242.     LONG Ambient;
  243.     G3DMATERIAL *Material;
  244.  
  245.     G3DLIGHT *Light;
  246.  
  247.     Light = Object->GetLightSource();
  248.     if (Light!=NULL)
  249.       {
  250.         ShadeTable = Light->GetShadeTable ();
  251.       } // End if
  252.     else
  253.       ShadeTable = NULL;
  254.  
  255.     Material = Poly->Material;
  256.  
  257.     _BlendBuffer = NULL;
  258.     
  259.     if (Material)
  260.       {
  261.         Ambient = Material->Ambient;
  262.         if ((Material->Attributes&MATERIAL_TRANSPARENT)&&(BlendTable!=NULL))
  263.           _BlendBuffer = BlendTable->GetTable()+Material->Transparency*256*256;
  264.       } // End if  
  265.     else
  266.       Ambient = Poly->Ambient;  
  267.  
  268.     _HazeBuffer = NULL;
  269.     if (DoHaze)
  270.       {
  271.         if (HazeTable!=NULL)
  272.           _HazeBuffer = HazeTable->GetTable ();  
  273.       } // End if
  274.     
  275.     LONG CurDetail = Object->GetCurDetail ();
  276.     if (CurDetail<MIN_DETAIL)
  277.       return;
  278.       
  279.     DetailData = Object->GetDetailData ( CurDetail );
  280.     GeometryData = Object->GetGeometryData ();
  281.     ScreenPoints = GeometryData->FLPScreenPoints;
  282.     CameraPoints = GeometryData->FLPCameraPoints;
  283.     PointIntensities = GeometryData->PointIntensities;
  284.     HazeValues = GeometryData->HazeValues;
  285.  
  286.     List0 = Poly->Points[0];
  287.     List1 = Poly->Points[1];
  288.     List2 = Poly->Points[2];
  289.  
  290.     float z0,z1,z2;
  291.     float MaxVisibleDistance;
  292.  
  293.     MaxVisibleDistance = Object->GetMaxVisibleDistance ();
  294.     
  295.     LONG ClipCode;
  296.     z0 = CameraPoints[List0].z;
  297.     z1 = CameraPoints[List1].z;
  298.     z2 = CameraPoints[List2].z;
  299.  
  300.     if ((z0>MaxVisibleDistance)&&(z1>MaxVisibleDistance)&&(z2>MaxVisibleDistance))
  301.       return;
  302.       
  303.     ClipCode = 0;
  304.     if (z0<MIN_Z_DISTANCE)
  305.       ClipCode |= ((LONG)1<<0);
  306.     if (z1<MIN_Z_DISTANCE)
  307.       ClipCode |= ((LONG)1<<1);
  308.     if (z2<MIN_Z_DISTANCE)
  309.       ClipCode |= ((LONG)1<<2);
  310.       
  311.     DrawShadeFlags = MinValue ( DetailData->ShadeFlags, ShadeFlags );
  312.     DrawFaceFlags = MinValue ( DetailData->FaceFlags, FaceFlags );
  313.     
  314.     ANIMIMAGE *Texture=NULL;    
  315.  
  316.     if (ClipCode==0)
  317.       {    
  318.         Points[0].x = (LONG)(ScreenPoints[List0].x)<<16; 
  319.         Points[0].y = (LONG)(ScreenPoints[List0].y);
  320.     
  321.         Points[1].x = (LONG)(ScreenPoints[List1].x)<<16;
  322.         Points[1].y = (LONG)(ScreenPoints[List1].y);
  323.     
  324.         Points[2].x = (LONG)(ScreenPoints[List2].x)<<16; 
  325.         Points[2].y = (LONG)(ScreenPoints[List2].y);
  326.  
  327.         if (DoHaze)
  328.           {
  329.             Points[0].Haze = (LONG)(HazeValues[List0]);  
  330.             Points[1].Haze = (LONG)(HazeValues[List1]);  
  331.             Points[2].Haze = (LONG)(HazeValues[List2]);  
  332.           } // End if
  333.         
  334.         if (DrawFaceFlags>=FACE_SOLID)
  335.           {
  336.             if (DrawShadeFlags==SHADE_GOURAUD)
  337.               {              
  338.                 Points[0].I = (LONG)(PointIntensities[List0]);  
  339.                 Points[1].I = (LONG)(PointIntensities[List1]);  
  340.                 Points[2].I = (LONG)(PointIntensities[List2]);  
  341.               } // End if
  342.             if ((DrawFaceFlags==FACE_TEXTURE)&&Material!=NULL)
  343.               {
  344.                 Points[0].u = (LONG)(Poly->TexCoords[0].x);  
  345.                 Points[0].v = (LONG)(Poly->TexCoords[0].y);  
  346.                 Points[1].u = (LONG)(Poly->TexCoords[1].x);  
  347.                 Points[1].v = (LONG)(Poly->TexCoords[1].y);  
  348.                 Points[2].u = (LONG)(Poly->TexCoords[2].x);  
  349.                 Points[2].v = (LONG)(Poly->TexCoords[2].y);
  350.  
  351.                 Texture = Material->GetTexture ();
  352.               } // End if  
  353.             DrawPolyFast ( Points, Texture, (LONG)(Poly->Intensity), Ambient, DrawShadeFlags,
  354.                            DrawFaceFlags );
  355.           } // End if  
  356.         else // Wire Frame
  357.           {
  358.             Grafix.FGColor = Ambient;  
  359.             Grafix.DrawLine ( Dest, Points[0].x>>16, Points[0].y,
  360.                                     Points[1].x>>16, Points[1].y );
  361.             Grafix.DrawLine ( Dest, Points[1].x>>16, Points[1].y,
  362.                                     Points[2].x>>16, Points[2].y );
  363.             Grafix.DrawLine ( Dest, Points[2].x>>16, Points[2].y,
  364.                                     Points[0].x>>16, Points[0].y );
  365.           } // End else  
  366.       } // End if
  367.     else if (ClipCode==7) // Triangle is completely behind minmum z    
  368.       {
  369.         return;  
  370.       } // End else
  371.     else // Z Clipping is necessary
  372.       {
  373.         CLIPPOINT3D SrcPoints[3];
  374.         CLIPPOINT3D ClippedPoints[4];
  375.         LONG NumClippedPoints;
  376.  
  377.         SrcPoints[0].x = CameraPoints[List0].x;
  378.         SrcPoints[0].y = CameraPoints[List0].y;
  379.         SrcPoints[0].z = z0;
  380.         SrcPoints[1].x = CameraPoints[List1].x;
  381.         SrcPoints[1].y = CameraPoints[List1].y;
  382.         SrcPoints[1].z = z1;
  383.         SrcPoints[2].x = CameraPoints[List2].x;
  384.         SrcPoints[2].y = CameraPoints[List2].y;
  385.         SrcPoints[2].z = z2;
  386.         
  387.         if (DoHaze)
  388.           {
  389.             SrcPoints[0].Haze = HazeValues[List0];  
  390.             SrcPoints[1].Haze = HazeValues[List1];  
  391.             SrcPoints[2].Haze = HazeValues[List2];  
  392.           } // End if        
  393.         if (DrawShadeFlags==SHADE_GOURAUD)
  394.           {              
  395.             SrcPoints[0].I = PointIntensities[List0];  
  396.             SrcPoints[1].I = PointIntensities[List1];  
  397.             SrcPoints[2].I = PointIntensities[List2];  
  398.           } // End if
  399.         if ((DrawFaceFlags==FACE_TEXTURE)&&Material!=NULL)
  400.           {
  401.             SrcPoints[0].u = Poly->TexCoords[0].x;  
  402.             SrcPoints[0].v = Poly->TexCoords[0].y;  
  403.             SrcPoints[1].u = Poly->TexCoords[1].x;  
  404.             SrcPoints[1].v = Poly->TexCoords[1].y;  
  405.             SrcPoints[2].u = Poly->TexCoords[2].x;  
  406.             SrcPoints[2].v = Poly->TexCoords[2].y;
  407.           } // End if
  408.           
  409.         NumClippedPoints = ZClip ( SrcPoints, ClippedPoints,
  410.                                    ClipCode, DrawShadeFlags, DrawFaceFlags );
  411.                                            
  412.         Points[0].x = (LONG)(ClippedPoints[0].x*ViewDistance/ClippedPoints[0].z + CenterX)<<16;
  413.         Points[0].y = (LONG)(-ClippedPoints[0].y*ViewDistance/ClippedPoints[0].z + CenterY);
  414.         Points[1].x = (LONG)(ClippedPoints[1].x*ViewDistance/ClippedPoints[1].z + CenterX)<<16;
  415.         Points[1].y = (LONG)(-ClippedPoints[1].y*ViewDistance/ClippedPoints[1].z + CenterY);
  416.         Points[2].x = (LONG)(ClippedPoints[2].x*ViewDistance/ClippedPoints[2].z + CenterX)<<16;
  417.         Points[2].y = (LONG)(-ClippedPoints[2].y*ViewDistance/ClippedPoints[2].z + CenterY);
  418.                 
  419.         if (DrawFaceFlags>=FACE_SOLID)
  420.           {
  421.             if (DoHaze)
  422.               {
  423.                 Points[0].Haze = (LONG)(ClippedPoints[0].Haze);  
  424.                 Points[1].Haze = (LONG)(ClippedPoints[1].Haze);  
  425.                 Points[2].Haze = (LONG)(ClippedPoints[2].Haze);  
  426.               } // End if
  427.         
  428.             if (DrawShadeFlags==SHADE_GOURAUD)
  429.               {              
  430.                 Points[0].I = (LONG)(ClippedPoints[0].I);  
  431.                 Points[1].I = (LONG)(ClippedPoints[1].I);  
  432.                 Points[2].I = (LONG)(ClippedPoints[2].I);  
  433.               } // End if
  434.             if ((DrawFaceFlags==FACE_TEXTURE)&&Material!=NULL)
  435.               {
  436.                 Points[0].u = (LONG)(ClippedPoints[0].u);  
  437.                 Points[0].v = (LONG)(ClippedPoints[0].v);  
  438.                 Points[1].u = (LONG)(ClippedPoints[1].u);  
  439.                 Points[1].v = (LONG)(ClippedPoints[1].v);  
  440.                 Points[2].u = (LONG)(ClippedPoints[2].u);  
  441.                 Points[2].v = (LONG)(ClippedPoints[2].v);  
  442.  
  443.                 Texture = Material->GetTexture ();
  444.               } // End if  
  445.             DrawPolyFast ( Points, Texture, (LONG)(Poly->Intensity), Ambient, DrawShadeFlags,
  446.                            DrawFaceFlags );
  447.             if (NumClippedPoints==4)
  448.               {
  449.                 Points[1] = Points[2];
  450.                 Points[2].x = (LONG)(ClippedPoints[3].x*ViewDistance/ClippedPoints[3].z + CenterX)<<16;
  451.                 Points[2].y = (LONG)(-ClippedPoints[3].y*ViewDistance/ClippedPoints[3].z + CenterY);
  452.                 Points[2].u = (LONG)(ClippedPoints[3].u);  
  453.                 Points[2].v = (LONG)(ClippedPoints[3].v);                  
  454.                 Points[2].I = (LONG)(ClippedPoints[3].I);
  455.                 Points[2].I = (LONG)(ClippedPoints[3].Haze);
  456.                 
  457.                 DrawPolyFast ( Points, Texture, (LONG)(Poly->Intensity), Ambient, DrawShadeFlags,
  458.                                DrawFaceFlags );
  459.               } // End if              
  460.           } // End if
  461.         else
  462.           {
  463.             if (NumClippedPoints<4)
  464.               {
  465.                 Grafix.FGColor = Ambient;  
  466.                 Grafix.DrawLine ( Dest, Points[0].x>>16, Points[0].y,
  467.                                         Points[1].x>>16, Points[1].y );
  468.                 Grafix.DrawLine ( Dest, Points[1].x>>16, Points[1].y,
  469.                                         Points[2].x>>16, Points[2].y );
  470.                 Grafix.DrawLine ( Dest, Points[2].x>>16, Points[2].y,
  471.                                         Points[0].x>>16, Points[0].y );                  
  472.               } // End if
  473.             else
  474.               {
  475.                 Grafix.FGColor = Ambient;  
  476.                 Grafix.DrawLine ( Dest, Points[0].x>>16, Points[0].y,
  477.                                         Points[1].x>>16, Points[1].y );
  478.                 Grafix.DrawLine ( Dest, Points[1].x>>16, Points[1].y,
  479.                                         Points[2].x>>16, Points[2].y );
  480.                 Grafix.DrawLine ( Dest, Points[2].x>>16, Points[2].y,
  481.                                         Points[3].x>>16, Points[3].y );                  
  482.                 Grafix.DrawLine ( Dest, Points[3].x>>16, Points[3].y,
  483.                                         Points[0].x>>16, Points[0].y );                  
  484.               } // End else                        
  485.           } // End else  
  486.       } // End else  
  487.   } // End of DrawPoly for G3DDRAW
  488.  
  489. LONG MIDDLEPOINTTABLE[4][4] = { { 1, 2, 1, 0 }, { 2, 0, 0, 0 },
  490.                                 { 1, 0, 0, 0 }, { 0, 0, 0, 0 } };
  491. FXPPOINT2D ExtraPoint;
  492. LONG AddedY;
  493.  
  494. BOOLEAN G3DDRAW::SortPolyHorz  ( FXPPOINT2D *Points, FXPDRAWSTRUCT *DrawStruct )
  495.   {
  496.     LONG TopIndex,BottomIndex,MiddleIndex;
  497.     FXPPOINT2D *PointPtr;    
  498.     FXPPOINT2D *Top,*Bottom,*Middle;    
  499.     FXPPOINT2D *Left,*Right;    
  500.     LONG MinY,MaxY;
  501.     LONG i;
  502.     
  503.     TopIndex = BottomIndex = 0;
  504.     PointPtr = Points;
  505.     MinY = MaxY = PointPtr->y;
  506.     for (i=1;i<3;i++)
  507.       {
  508.         LONG y;
  509.         PointPtr++;
  510.         y = PointPtr->y;
  511.         if (y<MinY)
  512.           {
  513.             MinY = y;
  514.             TopIndex = i;
  515.           } // End if  
  516.         else if (y>MaxY)
  517.           {
  518.             MaxY = y;
  519.             BottomIndex = i;
  520.           } // End if            
  521.       } // End for
  522.       
  523.     if (MinY>ViewPort.y2)
  524.       return FALSE;
  525.     else if (MaxY<ViewPort.y1)
  526.       return FALSE;
  527.  
  528.     MiddleIndex = MIDDLEPOINTTABLE[TopIndex][BottomIndex];
  529.         
  530.     Top = DrawStruct->Top = &(Points[TopIndex]);
  531.     Bottom = DrawStruct->Bottom = &(Points[BottomIndex]);
  532.     Middle = DrawStruct->Middle = &(Points[MiddleIndex]);
  533.  
  534.     LONG Case;
  535.     
  536.     if (Top->y==Bottom->y)
  537.       {
  538.         Case = DRAW_FLAT;
  539.         if (Top->x<Bottom->x)
  540.           {
  541.             if (Top->x<Middle->x)
  542.               {
  543.                 Left = Top;
  544.                 if (Middle->x<Bottom->x)
  545.                   Right = Bottom;
  546.                 else
  547.                   Right = Middle;  
  548.               } // End if  
  549.             else 
  550.               {
  551.                 Left = Middle;
  552.                 Right = Bottom;
  553.               } // End else if  
  554.           } // End if
  555.         else 
  556.           {
  557.             if (Bottom->x<Middle->x)
  558.               {
  559.                 Left = Bottom;
  560.                 if (Middle->x<Top->x)
  561.                   Right = Top;
  562.                 else
  563.                   Right = Middle;  
  564.               } // End if  
  565.             else
  566.               {
  567.                 Left = Middle;
  568.                 Right = Top;
  569.               } // End else  
  570.           } // End else  
  571.       } // End if  
  572.     else if (Top->y==Middle->y)
  573.       {
  574.         Case = DRAW_FLAT_TOP;
  575.         if (Top->x<Middle->x)
  576.           {
  577.             Left = Top;
  578.             Right = Middle;
  579.           } // End if
  580.         else  
  581.           {
  582.             Left = Middle;
  583.             Right = Top;
  584.           } // End if
  585.       } // End else if  
  586.     else if (Middle->y==Bottom->y)
  587.       {
  588.         Case = DRAW_FLAT_BOTTOM;
  589.         if (Bottom->x<Middle->x)
  590.           {
  591.             Left = Bottom;
  592.             Right = Middle;
  593.           } // End if
  594.         else  
  595.           {
  596.             Left = Middle;
  597.             Right = Bottom;
  598.           } // End if
  599.       } // End else if  
  600.     else
  601.       {
  602.         Case = DRAW_GENERAL;       
  603.         float Ratio;
  604.         Ratio = (float)(Middle->y-MinY)*DivTable[MaxY-MinY];
  605.         ExtraPoint.x = Top->x + (LONG)((Bottom->x-Top->x)*Ratio);
  606.         ExtraPoint.y = Bottom->y;
  607.  
  608.         if (ExtraPoint.x<Middle->x)
  609.           {
  610.             Left = &(ExtraPoint);
  611.             Right = Middle;
  612.           } // End if
  613.         else  
  614.           {
  615.             Left = Middle;
  616.             Right = &(ExtraPoint);
  617.           } // End if
  618.       } // End else  
  619.  
  620.     DrawStruct->Left = Left;
  621.     DrawStruct->Right = Right;
  622.     DrawStruct->Case = Case;
  623.     DrawStruct->Length = MaxY-MinY+1;
  624.     return TRUE;
  625.   } // End of SortPolyHorz for G3DDRAW
  626.  
  627. typedef VOID (*DrawRoutineType) ( LONG Color, LONG LoopCount, LONG SkipRow,
  628.                                    LONG SideClipped );
  629.                         
  630. VOID G3DDRAW::DrawPolyFast ( FXPPOINT2D *Points, ANIMIMAGE *Texture,
  631.                              LONG Intensity, LONG Color, LONG DrawShadeFlags,
  632.                              LONG DrawFaceFlags )
  633.   {    
  634.     FXPDRAWSTRUCT DrawStruct;
  635.     BOOLEAN Texmap=FALSE;
  636.     BOOLEAN Gouraud=FALSE;
  637.     BOOLEAN Flat=FALSE;
  638.     BOOLEAN Transparent = FALSE;
  639.     BOOLEAN Haze = FALSE;
  640.     LONG DrawColor;
  641.     DrawRoutineType DrawFunction;
  642.  
  643.     DrawColor = Color+(Color<<8)+(Color<<16)+(Color<<24);
  644.  
  645.     if (DrawFaceFlags==FACE_TEXTURE)
  646.       Texmap = TRUE;
  647.       
  648.     if (DoHaze)
  649.       {
  650.         if ((Points[0].Haze==Points[1].Haze)&&(Points[0].Haze==Points[2].Haze)&&
  651.              (Points[0].Haze==HazeTable->GetNumLevels()))
  652.           {
  653.             Haze = FALSE;  
  654.           } // End if
  655.         else
  656.           {
  657.             Haze = TRUE;
  658.           } // End else  
  659.       } // End if
  660.       
  661.     if (_BlendBuffer!=NULL)
  662.       {
  663.         Transparent = TRUE;
  664.         Haze = FALSE;
  665.       } // End if  
  666.       
  667.     if (DrawShadeFlags==SHADE_GOURAUD)
  668.       {
  669.         if (ShadeTable!=NULL)
  670.           {
  671.             _ShadeBuffer = ShadeTable->GetTable ();
  672.             Gouraud = TRUE;
  673.           } // End if  
  674.       } // End if
  675.     else if (DrawShadeFlags==SHADE_FLAT)
  676.       {
  677.         _LeftI = 0;
  678.         if (ShadeTable!=NULL)
  679.           {
  680.             _ShadeBuffer = ShadeTable->GetTable ();
  681.             Color = _ShadeBuffer[((LONG)Intensity>>16)*256+Color];
  682.             DrawColor = Color+(Color<<8)+(Color<<16)+(Color<<24);
  683.             Flat = TRUE;
  684.             _LeftI = Intensity;  
  685.           } // End if  
  686.       } // End if
  687.  
  688.     _DivTable = DivTable;
  689.       
  690.     _SetViewPortData ( ViewPort.x1, ViewPort.y1, ViewPort.x2, ViewPort.y2 );
  691.     if (SortPolyHorz ( Points,  &DrawStruct )==FALSE)
  692.       return;
  693.         
  694.     float LeftRatio,RightRatio;
  695.     LONG Tx,Ty,Bx,By,Lx,Ly,Rx,Ry;
  696.     LONG Tu,Tv,Bu,Bv,Lu,Lv,Ru,Rv;
  697.     LONG TI,BI,LI,RI;
  698.     LONG THaze,BHaze,LHaze,RHaze;
  699.     LONG My;
  700.     LONG Height;
  701.  
  702.     Tx = DrawStruct.Top->x;
  703.     Ty = DrawStruct.Top->y;
  704.     Bx = DrawStruct.Bottom->x;
  705.     By = DrawStruct.Bottom->y;
  706.     Lx = DrawStruct.Left->x;
  707.     Ly = DrawStruct.Left->y;
  708.     Rx = DrawStruct.Right->x;
  709.     Ry = DrawStruct.Right->y;
  710.  
  711.     if (Texmap)
  712.       {
  713.         _TextureBuffer = Texture->GetBuffer ();
  714.         Tu = DrawStruct.Top->u;
  715.         Tv = DrawStruct.Top->v;
  716.         Bu = DrawStruct.Bottom->u;
  717.         Bv = DrawStruct.Bottom->v;
  718.         Lu = DrawStruct.Left->u;
  719.         Lv = DrawStruct.Left->v;
  720.         Ru = DrawStruct.Right->u;
  721.         Rv = DrawStruct.Right->v;
  722.  
  723.         if (Gouraud)
  724.           {
  725.             TI = DrawStruct.Top->I;
  726.             BI = DrawStruct.Bottom->I;
  727.             LI = DrawStruct.Left->I;
  728.             RI = DrawStruct.Right->I;
  729.             
  730.             if (Transparent)
  731.               DrawFunction = _DrawTextureGrdTransHorz;
  732.             else
  733.               {
  734.                 if (Haze)
  735.                   {
  736.                     THaze = DrawStruct.Top->Haze;
  737.                     BHaze = DrawStruct.Bottom->Haze;
  738.                     LHaze = DrawStruct.Left->Haze;
  739.                     RHaze = DrawStruct.Right->Haze;            
  740.                     DrawFunction = _DrawTextureGrdHazeHorz;
  741.                   } // End if
  742.                 else                    
  743.                   DrawFunction = _DrawTextureGrdHorz;
  744.               } // End if
  745.           } // End if
  746.         else if (Flat)
  747.           {
  748.             if (Transparent)
  749.               DrawFunction = _DrawTextureFlatTransHorz;
  750.             else
  751.               {
  752.                 if (Haze)
  753.                   {
  754.                     THaze = DrawStruct.Top->Haze;
  755.                     BHaze = DrawStruct.Bottom->Haze;
  756.                     LHaze = DrawStruct.Left->Haze;
  757.                     RHaze = DrawStruct.Right->Haze;            
  758.                     DrawFunction = _DrawTextureFlatHazeHorz;
  759.                   } // End if
  760.                 else                    
  761.                   DrawFunction = _DrawTextureFlatHorz;
  762.               } // End else  
  763.           } // End else if  
  764.         else
  765.           {
  766.             if (Transparent)
  767.               DrawFunction = _DrawTextureNoTransHorz;
  768.             else
  769.               {
  770.                 if (Haze)
  771.                   {
  772.                     THaze = DrawStruct.Top->Haze;
  773.                     BHaze = DrawStruct.Bottom->Haze;
  774.                     LHaze = DrawStruct.Left->Haze;
  775.                     RHaze = DrawStruct.Right->Haze;            
  776.                     DrawFunction = _DrawTextureNoHazeHorz;
  777.                   } // End if
  778.                 else                    
  779.                   DrawFunction = _DrawTextureNoHorz;
  780.               } // End else    
  781.           } // End else  
  782.       } // End if
  783.     else
  784.       {
  785.         if (Gouraud)
  786.           {
  787.             TI = DrawStruct.Top->I;
  788.             BI = DrawStruct.Bottom->I;
  789.             LI = DrawStruct.Left->I;
  790.             RI = DrawStruct.Right->I;
  791.              
  792.             if (Transparent)
  793.               DrawFunction = _DrawSolidGrdTransHorz;
  794.             else
  795.               {
  796.                 if (Haze)
  797.                   {
  798.                     THaze = DrawStruct.Top->Haze;
  799.                     BHaze = DrawStruct.Bottom->Haze;
  800.                     LHaze = DrawStruct.Left->Haze;
  801.                     RHaze = DrawStruct.Right->Haze;            
  802.                     DrawFunction = _DrawSolidGrdHazeHorz;
  803.                   } // End if
  804.                 else                    
  805.                   DrawFunction = _DrawSolidGrdHorz;
  806.               } // End else    
  807.           } // End if
  808.         else
  809.           {
  810.             if (Transparent)
  811.               DrawFunction = _DrawSolidNoTransHorz;
  812.             else
  813.               {
  814.                 if (Haze)
  815.                   {
  816.                     THaze = DrawStruct.Top->Haze;
  817.                     BHaze = DrawStruct.Bottom->Haze;
  818.                     LHaze = DrawStruct.Left->Haze;
  819.                     RHaze = DrawStruct.Right->Haze;            
  820.                     DrawFunction = _DrawSolidNoHazeHorz;
  821.                   } // End if
  822.                 else                    
  823.                   DrawFunction = _DrawSolidNoHorz;
  824.               } // End else    
  825.           } // End else  
  826.       } // End else      
  827.         
  828.     _DestBuffer = Dest->SetOffset ( 0, 0 );
  829.     _AddDest = Dest->GetRowInc ();
  830.     _DestBuffer += _AddDest*Ty;
  831.  
  832.     BOOLEAN SideClipped = FALSE;
  833.     LONG SkipRow;
  834.     LONG ClipTx,ClipBx,ClipRx,ClipLx;
  835.     ClipTx = Tx>>16;
  836.     ClipBx = Bx>>16;
  837.     ClipLx = Lx>>16;
  838.     ClipRx = Rx>>16;
  839.     
  840.     if ((ClipTx<ViewPort.x1)||(ClipTx>ViewPort.x2)||
  841.          (ClipLx<ViewPort.x1)||(ClipLx>ViewPort.x2)||
  842.           (ClipRx<ViewPort.x1)||(ClipRx>ViewPort.x2)||
  843.            (ClipBx<ViewPort.x1)||(ClipBx>ViewPort.x2))
  844.       SideClipped = TRUE;
  845.  
  846.     switch (DrawStruct.Case)
  847.       {
  848.         case DRAW_FLAT_TOP :
  849.           Height = DrawStruct.Length;
  850.           LeftRatio = DivTable[By-Ly];
  851.           RightRatio = DivTable[By-Ry];
  852.  
  853.           SkipRow = 0;
  854.           if (Ty<ViewPort.y1)
  855.             {
  856.               SkipRow = ViewPort.y1-Ty;
  857.             } // End if
  858.           if (By>ViewPort.y2)
  859.             Height = ViewPort.y2-Ty+1;
  860.  
  861.           _LeftX = (LONG)(Lx);
  862.           _RightX = (LONG)(Rx);
  863.           _LeftDx = (LONG)((Bx-Lx)*LeftRatio);
  864.           _RightDx = (LONG)((Bx-Rx)*RightRatio);
  865.  
  866.           if (Texmap)
  867.             {
  868.               _LeftU = (LONG)(Lu);
  869.               _RightU = (LONG)(Ru);
  870.               _LeftDu = (LONG)((Bu-Lu)*LeftRatio);
  871.               _RightDu = (LONG)((Bu-Ru)*RightRatio);
  872.  
  873.               _LeftV = (LONG)(Lv);
  874.               _RightV = (LONG)(Rv);
  875.               _LeftDv = (LONG)((Bv-Lv)*LeftRatio);
  876.               _RightDv = (LONG)((Bv-Rv)*RightRatio);
  877.             } // End if    
  878.  
  879.           if (Gouraud)
  880.             {
  881.               _LeftI = (LONG)(LI);
  882.               _RightI = (LONG)(RI);
  883.               _LeftDI = (LONG)((BI-LI)*LeftRatio);
  884.               _RightDI = (LONG)((BI-RI)*RightRatio);
  885.             } // End if
  886.             
  887.           if (Haze)
  888.             {
  889.               _LeftH = (LONG)(LHaze);
  890.               _RightH = (LONG)(RHaze);
  891.               _LeftDh = (LONG)((BHaze-LHaze)*LeftRatio);
  892.               _RightDh = (LONG)((BHaze-RHaze)*RightRatio);
  893.             } // End if
  894.             
  895.           DrawFunction ( DrawColor, Height, SkipRow, SideClipped );
  896.           break;
  897.  
  898.         case DRAW_FLAT_BOTTOM :
  899.           Height = DrawStruct.Length;
  900.           LeftRatio = DivTable[Ly-Ty];
  901.           RightRatio = DivTable[Ry-Ty];
  902.  
  903.           SkipRow = 0;
  904.           if (Ty<ViewPort.y1)
  905.             {
  906.               SkipRow = ViewPort.y1-Ty;
  907.             } // End if
  908.           if (By>ViewPort.y2)
  909.             Height = ViewPort.y2-Ty+1;
  910.  
  911.           _LeftX = (LONG)(Tx);
  912.           _RightX = _LeftX;
  913.           _LeftDx = (LONG)((Lx-Tx)*LeftRatio);
  914.           _RightDx = (LONG)((Rx-Tx)*RightRatio);
  915.  
  916.           if (Texmap)
  917.             {
  918.               _LeftU = (LONG)(Tu);
  919.               _RightU = _LeftU;
  920.               _LeftDu = (LONG)((Lu-Tu)*LeftRatio);
  921.               _RightDu = (LONG)((Ru-Tu)*RightRatio);
  922.           
  923.               _LeftV = (LONG)(Tv);
  924.               _RightV = _LeftV;
  925.               _LeftDv = (LONG)((Lv-Tv)*LeftRatio);
  926.               _RightDv = (LONG)((Rv-Tv)*RightRatio);
  927.             } // End if    
  928.           
  929.           if (Gouraud)
  930.             {
  931.               _LeftI = (LONG)(TI);
  932.               _RightI = _LeftI;
  933.               _LeftDI = (LONG)((LI-TI)*LeftRatio);
  934.               _RightDI = (LONG)((RI-TI)*RightRatio);
  935.             } // End if
  936.             
  937.           if (Haze)
  938.             {
  939.               _LeftH = (LONG)(THaze);
  940.               _RightH = _LeftH;
  941.               _LeftDh = (LONG)((LHaze-THaze)*LeftRatio);
  942.               _RightDh = (LONG)((RHaze-THaze)*RightRatio);
  943.             } // End if
  944.             
  945.           DrawFunction ( DrawColor, Height, SkipRow, SideClipped );
  946.           break;
  947.  
  948.         case DRAW_FLAT :
  949.           Height = 1;
  950.           SkipRow = 0;
  951.           
  952.           _LeftX = (LONG)(Lx);
  953.           _RightX = (LONG)(Rx);
  954.           _LeftDx = 0;
  955.           _RightDx = 0;
  956.           
  957.           if (Texmap)
  958.             {
  959.               _LeftU = (LONG)(Lu);
  960.               _RightU = (LONG)(Ru);
  961.               _LeftDu = 0;
  962.               _RightDu = 0;
  963.           
  964.               _LeftV = (LONG)(Lv);
  965.               _RightV = (LONG)(Rv);
  966.               _LeftDv = 0;
  967.               _RightDv = 0;
  968.             } // End if
  969.           
  970.           if (Gouraud)
  971.             {
  972.               _LeftI = (LONG)(LI);
  973.               _RightI = (LONG)(RI);
  974.               _LeftDI = 0;
  975.               _RightDI = 0;
  976.             } // End if
  977.             
  978.           if (Haze)
  979.             {
  980.               _LeftH = (LONG)(LHaze);
  981.               _RightH = (LONG)(RHaze);
  982.               _LeftDh = 0;
  983.               _RightDh = 0;
  984.             } // End if
  985.             
  986.           DrawFunction ( DrawColor, Height, SkipRow, SideClipped );
  987.           break;
  988.  
  989.         case DRAW_GENERAL :
  990.           // Draw Top Half
  991.           My = DrawStruct.Middle->y;
  992.           Height = My-Ty;
  993.           LeftRatio = DivTable[Ly-Ty];
  994.           RightRatio = DivTable[Ry-Ty];
  995.  
  996.           SkipRow = 0;
  997.           if (Ty<ViewPort.y1)
  998.             {
  999.               SkipRow = ViewPort.y1-Ty;
  1000.             } // End if
  1001.           if (My>ViewPort.y2)
  1002.             Height = ViewPort.y2-Ty+1;
  1003.  
  1004.           _LeftX = (LONG)(Tx);
  1005.           _RightX = _LeftX;
  1006.           
  1007.           if (Rx==ExtraPoint.x)
  1008.             {
  1009.               _LeftDx = (LONG)((Lx-Tx)*LeftRatio);
  1010.               _RightDx = (LONG)((Bx-Tx)*RightRatio);
  1011.                       
  1012.               if (Texmap)
  1013.                 {
  1014.                   _LeftU = (LONG)(Tu);
  1015.                   _RightU = _LeftU;
  1016.           
  1017.                   _LeftV = (LONG)(Tv);
  1018.                   _RightV = _LeftV;
  1019.           
  1020.                   _LeftDu = (LONG)((Lu-Tu)*LeftRatio);
  1021.                   _RightDu = (LONG)((Bu-Tu)*RightRatio);
  1022.                   _LeftDv = (LONG)((Lv-Tv)*LeftRatio);
  1023.                   _RightDv = (LONG)((Bv-Tv)*RightRatio);
  1024.                 } // End if
  1025.               if (Gouraud)
  1026.                 {
  1027.                   _LeftI = (LONG)(TI);
  1028.                   _RightI = _LeftI;
  1029.                   _LeftDI = (LONG)((LI-TI)*LeftRatio);
  1030.                   _RightDI = (LONG)((BI-TI)*RightRatio);
  1031.                 } // End if  
  1032.               if (Haze)
  1033.                 {
  1034.                   _LeftH = (LONG)(THaze);
  1035.                   _RightH = _LeftH;
  1036.                   _LeftDh = (LONG)((LHaze-THaze)*LeftRatio);
  1037.                   _RightDh = (LONG)((BHaze-THaze)*RightRatio);
  1038.                 } // End if  
  1039.             } // End if
  1040.           else
  1041.             {
  1042.               _LeftDx = (LONG)((Bx-Tx)*LeftRatio);
  1043.               _RightDx = (LONG)((Rx-Tx)*RightRatio);
  1044.                       
  1045.               if (Texmap)
  1046.                 {
  1047.                   _LeftU = (LONG)(Tu);
  1048.                   _RightU = _LeftU;
  1049.           
  1050.                   _LeftV = (LONG)(Tv);
  1051.                   _RightV = _LeftV;
  1052.           
  1053.                   _LeftDu = (LONG)((Bu-Tu)*LeftRatio);
  1054.                   _RightDu = (LONG)((Ru-Tu)*RightRatio);
  1055.                   _LeftDv = (LONG)((Bv-Tv)*LeftRatio);
  1056.                   _RightDv = (LONG)((Rv-Tv)*RightRatio);
  1057.                 } // End if
  1058.               if (Gouraud)
  1059.                 {
  1060.                   _LeftI = (LONG)(TI);
  1061.                   _RightI = _LeftI;
  1062.                   _LeftDI = (LONG)((BI-TI)*LeftRatio);
  1063.                   _RightDI = (LONG)((RI-TI)*RightRatio);
  1064.                 } // End if  
  1065.               if (Haze)
  1066.                 {
  1067.                   _LeftH = (LONG)(THaze);
  1068.                   _RightH = _LeftH;
  1069.                   _LeftDh = (LONG)((BHaze-THaze)*LeftRatio);
  1070.                   _RightDh = (LONG)((RHaze-THaze)*RightRatio);
  1071.                 } // End if  
  1072.             } // End else 
  1073.             
  1074.            if (SkipRow<=Height)
  1075.             { 
  1076.               DrawFunction ( DrawColor, Height, SkipRow, SideClipped );
  1077.               SkipRow = 0;
  1078.             } // End if
  1079.            else
  1080.             {
  1081.               SkipRow -= Height;
  1082.               DrawFunction ( DrawColor, Height, Height, SideClipped );
  1083.             } // End else 
  1084.  
  1085.           // Draw Bottom Half
  1086.           Height = By-My+1;
  1087.  
  1088.           if (By>ViewPort.y2)
  1089.             Height = ViewPort.y2-My+1;
  1090.           
  1091.           if (Rx==ExtraPoint.x)
  1092.             {
  1093.               LeftRatio = DivTable[By-Ly];
  1094.               _LeftDx = (LONG)((Bx-Lx)*LeftRatio);
  1095.               _LeftX = (LONG)(Lx);
  1096.  
  1097.               if (Gouraud)
  1098.                 {
  1099.                   _LeftI = (LONG)(LI);
  1100.                   _LeftDI = (LONG)((BI-LI)*LeftRatio);
  1101.                 } // End if
  1102.               if (Haze)
  1103.                 {
  1104.                   _LeftH = (LONG)(LHaze);
  1105.                   _LeftDh = (LONG)((BHaze-LHaze)*LeftRatio);
  1106.                 } // End if
  1107.               if (Texmap)
  1108.                 {
  1109.                   _LeftU = (LONG)(Lu);
  1110.                   _LeftV = (LONG)(Lv);
  1111.                   _LeftDu = (LONG)((Bu-Lu)*LeftRatio);
  1112.                   _LeftDv = (LONG)((Bv-Lv)*LeftRatio);
  1113.                 } // End if  
  1114.             } // End if
  1115.           else
  1116.             {
  1117.               RightRatio = DivTable[By-Ry];
  1118.               _RightDx = (LONG)((Bx-Rx)*RightRatio);
  1119.               _RightX = (LONG)(Rx);
  1120.  
  1121.               if (Gouraud)
  1122.                 {
  1123.                   _RightI = (LONG)(RI);
  1124.                   _RightDI = (LONG)((BI-RI)*RightRatio);
  1125.                 } // End if
  1126.               if (Haze)
  1127.                 {
  1128.                   _RightH = (LONG)(RHaze);
  1129.                   _RightDh = (LONG)((BHaze-RHaze)*RightRatio);
  1130.                 } // End if
  1131.               if (Texmap)
  1132.                 {
  1133.                   _RightU = (LONG)(Ru);
  1134.                   _RightV = (LONG)(Rv);
  1135.                   _RightDu = (LONG)((Bu-Ru)*RightRatio);
  1136.                   _RightDv = (LONG)((Bv-Rv)*RightRatio);
  1137.                 } // End if
  1138.             } // End else
  1139.  
  1140.           DrawFunction ( DrawColor, Height, SkipRow, SideClipped );
  1141.           break;
  1142.       } // End switch
  1143.   } // End of DrawPolyFast for G3DDRAW
  1144.  
  1145. RECTANGLE G3DDRAW::GetViewPort ()
  1146.   {
  1147.     RECTANGLE VPort;
  1148.       
  1149.     if (Dest==NULL)
  1150.       return VPort;
  1151.     VPort = Dest->GetViewPort ();
  1152.     return VPort;    
  1153.   } // End of GetViewPort for G3DDRAW
  1154.  
  1155. float G3DDRAW::GetNearClipZ ()
  1156.   {
  1157.     return MIN_Z_DISTANCE;   
  1158.   } // End of GetNearClipZ for G3DDRAW
  1159.   
  1160. VOID G3DDRAW::SetViewPort ( LONG x1, LONG y1, LONG x2, LONG y2 )
  1161.   {
  1162.     if (Dest!=NULL)
  1163.       {
  1164.         Dest->SetViewPort ( x1, y1, x2, y2 );
  1165.         ViewPort = Dest->GetViewPort ();
  1166.       } // End if
  1167.   } // End of SetViewPort for G3DDRAW
  1168.   
  1169. VOID G3DDRAW::SetNearClipZ ( float Z )
  1170.   {
  1171.     MIN_Z_DISTANCE = Z;  
  1172.   } // End of SetNearClipZ for G3DDRAW
  1173.  
  1174.  
  1175.  
  1176. typedef FXPEDGE* (*ScanEdgeType) ( FXPPOINT2D *Point1, FXPPOINT2D *Point2,
  1177.                                    FXPEDGE *EdgePtr, LONG ExtraHt );
  1178. typedef VOID (*DrawPolyType) ( LONG Color, LONG Intensity,
  1179.                                LONG Skip, LONG LoopCount );
  1180.  
  1181. struct DRAWROUTINE
  1182.   {
  1183.     ScanEdgeType ScanEdgePtr;
  1184.     DrawPolyType DrawPolyPtr;
  1185.   }; // End of DRAWROUTINE
  1186.  
  1187.                     //  Shade Face Haze Trans
  1188. DRAWROUTINE DrawRoutine [3]   [3]  [2]  [2];
  1189.  
  1190. VOID G3DDRAW::InitFunctionTable ()
  1191.   {
  1192.     #if defined (__FORWATCOM__)
  1193.     DrawRoutine[SHADE_NONE][FACE_WIREFRAME][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1194.     DrawRoutine[SHADE_NONE][FACE_WIREFRAME][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1195.  
  1196.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1197.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1198.  
  1199.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1200.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1201.  
  1202.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1203.       DrawRoutine[SHADE_NONE][FACE_WIREFRAME][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1204.  
  1205.       DrawRoutine[SHADE_NONE][FACE_SOLID][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1206.       DrawRoutine[SHADE_NONE][FACE_SOLID][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1207.  
  1208.       DrawRoutine[SHADE_NONE][FACE_SOLID][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1209.       DrawRoutine[SHADE_NONE][FACE_SOLID][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1210.  
  1211.       DrawRoutine[SHADE_NONE][FACE_SOLID][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1212.       DrawRoutine[SHADE_NONE][FACE_SOLID][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1213.  
  1214.       DrawRoutine[SHADE_NONE][FACE_SOLID][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1215.       DrawRoutine[SHADE_NONE][FACE_SOLID][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1216.  
  1217.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][FALSE][FALSE].ScanEdgePtr = _ScanEdgeTexture;
  1218.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][FALSE][FALSE].DrawPolyPtr = _DrawTexturePoly;
  1219.  
  1220.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][FALSE][TRUE].ScanEdgePtr = _ScanEdgeTexture;
  1221.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][FALSE][TRUE].DrawPolyPtr = _DrawTexturePoly;
  1222.  
  1223.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][TRUE][FALSE].ScanEdgePtr = _ScanEdgeTexture;
  1224.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][TRUE][FALSE].DrawPolyPtr = _DrawTexturePoly;
  1225.  
  1226.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][TRUE][TRUE].ScanEdgePtr = _ScanEdgeTexture;
  1227.       DrawRoutine[SHADE_NONE][FACE_TEXTURE][TRUE][TRUE].DrawPolyPtr = _DrawTexturePoly;
  1228.  
  1229.     DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1230.     DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1231.  
  1232.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1233.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1234.  
  1235.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1236.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1237.  
  1238.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1239.       DrawRoutine[SHADE_FLAT][FACE_WIREFRAME][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1240.  
  1241.       DrawRoutine[SHADE_FLAT][FACE_SOLID][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1242.       DrawRoutine[SHADE_FLAT][FACE_SOLID][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1243.  
  1244.       DrawRoutine[SHADE_FLAT][FACE_SOLID][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1245.       DrawRoutine[SHADE_FLAT][FACE_SOLID][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1246.  
  1247.       DrawRoutine[SHADE_FLAT][FACE_SOLID][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1248.       DrawRoutine[SHADE_FLAT][FACE_SOLID][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1249.  
  1250.       DrawRoutine[SHADE_FLAT][FACE_SOLID][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1251.       DrawRoutine[SHADE_FLAT][FACE_SOLID][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1252.  
  1253.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1254.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1255.  
  1256.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1257.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1258.  
  1259.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1260.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1261.  
  1262.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1263.       DrawRoutine[SHADE_FLAT][FACE_TEXTURE][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1264.  
  1265.     DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1266.     DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1267.  
  1268.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1269.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1270.  
  1271.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1272.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1273.  
  1274.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1275.       DrawRoutine[SHADE_GOURAUD][FACE_WIREFRAME][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1276.  
  1277.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolidGouraud;
  1278.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][FALSE][FALSE].DrawPolyPtr = _DrawSolidGouraudPoly;
  1279.  
  1280.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolidGouraud;
  1281.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][FALSE][TRUE].DrawPolyPtr = _DrawSolidGouraudPoly;
  1282.  
  1283.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolidGouraud;
  1284.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][TRUE][FALSE].DrawPolyPtr = _DrawSolidGouraudPoly;
  1285.  
  1286.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolidGouraud;
  1287.       DrawRoutine[SHADE_GOURAUD][FACE_SOLID][TRUE][TRUE].DrawPolyPtr = _DrawSolidGouraudPoly;
  1288.  
  1289.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][FALSE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1290.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][FALSE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1291.  
  1292.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][FALSE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1293.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][FALSE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1294.  
  1295.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][TRUE][FALSE].ScanEdgePtr = _ScanEdgeSolid;
  1296.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][TRUE][FALSE].DrawPolyPtr = _DrawSolidPoly;
  1297.  
  1298.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][TRUE][TRUE].ScanEdgePtr = _ScanEdgeSolid;
  1299.       DrawRoutine[SHADE_GOURAUD][FACE_TEXTURE][TRUE][TRUE].DrawPolyPtr = _DrawSolidPoly;
  1300.     #endif
  1301.   } // End of InitFunctionTable for G3DDRAW
  1302.  
  1303.  
  1304. VOID G3DDRAW::TestDrawTriangle ( FXPPOINT2D *Points, ANIMIMAGE *Texture,
  1305.                                  LONG Intensity, LONG Color, LONG DrawShadeFlags,
  1306.                                  LONG DrawFaceFlags, COLORTABLE *BlendTBL, COLORTABLE *ShadeTBL,
  1307.                                  COLORTABLE *HazeTBL )
  1308.   {
  1309.     ShadeTable = ShadeTBL;
  1310.     HazeTable = HazeTBL;
  1311.     if (BlendTBL!=NULL)
  1312.       _BlendBuffer = NULL;
  1313.     else
  1314.       _BlendBuffer = NULL;  
  1315.  
  1316.     DrawPolyFast ( Points, Texture, Intensity, Color, DrawShadeFlags, DrawFaceFlags );
  1317.   } // End of TestDrawTriangle for G3DDRAW                                 
  1318.  
  1319. FLPPOINT2D* FLPEdge1Index[8];
  1320. FLPPOINT2D* FLPEdge2Index[8];
  1321. FXPPOINT2D* FXPEdge1Index[8];
  1322. FXPPOINT2D* FXPEdge2Index[8];
  1323. LONG NumEdge1;
  1324. LONG NumEdge2;
  1325.  
  1326. VOID G3DDRAW::CreateFLPEdgeTable ( FLPPOINT2D *Points, LONG NumPoints )
  1327.   {
  1328.     LONG i;
  1329.     LONG TopIndex,BottomIndex;
  1330.     float TopY,BottomY;
  1331.     FLPPOINT2D *PointPtr;
  1332.  
  1333.     PointPtr = Points;
  1334.  
  1335.     FLPPOINT2D *FirstPtr,*LastPtr;
  1336.     FirstPtr = Points;
  1337.     LastPtr = &(Points[NumPoints-1]);
  1338.  
  1339.     TopY = PointPtr->y;
  1340.     BottomY = TopY;
  1341.  
  1342.     PointPtr++;
  1343.  
  1344.     TopIndex = BottomIndex = 0;
  1345.  
  1346.     float y;
  1347.     for (i=0;i<NumPoints;i++)
  1348.       {
  1349.         y = PointPtr->y;
  1350.         if (y<TopY)
  1351.           {
  1352.             TopIndex = i;
  1353.             TopY = y;
  1354.           } // End if
  1355.         else if (y>BottomY)
  1356.           {
  1357.             BottomIndex = i;
  1358.             BottomY = y;
  1359.           } // End else if
  1360.         PointPtr++;
  1361.       }; // End while
  1362.  
  1363.     if (BottomY==TopY)
  1364.       return;
  1365.  
  1366.     FLPEdgeTable->Start = TopY;
  1367.     FLPEdgeTable->Length = (LONG)(BottomY-TopY)+1;
  1368.  
  1369.     FLPPOINT2D *NextPtr;
  1370.     FLPPOINT2D **PointPtrPtr;
  1371.  
  1372.     // Sort Increase side
  1373.     NumEdge1 = 0;
  1374.     NextPtr = &(Points[TopIndex]);
  1375.     y = TopY;
  1376.     PointPtrPtr = FLPEdge1Index;
  1377.  
  1378.     while (y<BottomY)
  1379.       {
  1380.         PointPtr = NextPtr;
  1381.         if (NextPtr<LastPtr)
  1382.           NextPtr++;
  1383.         else
  1384.           NextPtr = FirstPtr;
  1385.         if ((y==TopY)&&(NextPtr->y!=TopY))
  1386.           {
  1387.             *(PointPtrPtr++) = PointPtr;
  1388.             y = PointPtr->y;
  1389.             NumEdge1++;
  1390.           } // End if
  1391.       } // End if
  1392.  
  1393.     // Sort Decrease side
  1394.     NumEdge2 = 0;
  1395.     NextPtr = &(Points[TopIndex]);
  1396.     y = TopY;
  1397.     PointPtrPtr = FLPEdge2Index;
  1398.  
  1399.     while (y<BottomY)
  1400.       {
  1401.         PointPtr = NextPtr;
  1402.         if (NextPtr>FirstPtr)
  1403.           NextPtr--;
  1404.         else
  1405.           NextPtr = LastPtr;
  1406.         if ((y==TopY)&&(NextPtr->y!=TopY))
  1407.           {
  1408.             *(PointPtrPtr++) = PointPtr;
  1409.             y = PointPtr->y;
  1410.             NumEdge2++;
  1411.           } // End if
  1412.       } // End if
  1413.  
  1414.     float x;
  1415.     float Dx,Dy;
  1416.     LONG EdgeLength;
  1417.     FLPPOINT2D *Point1,*Point2;
  1418.     FLPEDGE *EdgePtr;
  1419.  
  1420.     // Create Edge1 table
  1421.     EdgePtr = FLPEdge1;
  1422.     for (i=0;i<NumEdge1-1;i++)
  1423.       {
  1424.         Point1 = FLPEdge1Index[i];
  1425.         Point2 = FLPEdge1Index[i+1];
  1426.         Dy = Point2->y-Point1->y;
  1427.         x = Point1->x;
  1428.         Dx = Point2->x-x;
  1429.  
  1430.         EdgeLength = (LONG)Dy;
  1431.         if (i==NumEdge1-2)
  1432.           EdgeLength++;
  1433.  
  1434.         Dy = (float)1/Dy;
  1435.         Dx *= Dy;
  1436.  
  1437.         while (EdgeLength--)
  1438.           {
  1439.             EdgePtr->x = x;
  1440.             x += Dx;
  1441.             EdgePtr++;
  1442.           } // End while
  1443.       } // End for
  1444.  
  1445.     // Create Edge2 table
  1446.     EdgePtr = FLPEdge2;
  1447.     for (i=0;i<NumEdge2-1;i++)
  1448.       {
  1449.         Point1 = FLPEdge2Index[i];
  1450.         Point2 = FLPEdge2Index[i+1];
  1451.         Dy = Point2->y-Point1->y;
  1452.         x = Point1->x;
  1453.         Dx = Point2->x-x;
  1454.  
  1455.         EdgeLength = (LONG)Dy;
  1456.         if (i==NumEdge1-2)
  1457.           EdgeLength++;
  1458.  
  1459.         Dy = (float)1/Dy;
  1460.         Dx *= Dy;
  1461.  
  1462.         while (EdgeLength--)
  1463.           {
  1464.             EdgePtr->x = x;
  1465.             x += Dx;
  1466.             EdgePtr++;
  1467.           } // End while
  1468.       } // End for
  1469.  
  1470.     // Compare which one is the left and right
  1471.     FLPEdgeTable->Edge1 = FLPEdge1;
  1472.     FLPEdgeTable->Edge2 = FLPEdge2;
  1473.  
  1474.     for (i=0;FLPEdgeTable->Length;i++)
  1475.       {
  1476.         if (FLPEdge1[i].x<FLPEdge2[i].x)
  1477.           {
  1478.             FLPEdgeTable->Edge1 = FLPEdge1;
  1479.             FLPEdgeTable->Edge2 = FLPEdge2;
  1480.             break;
  1481.           } // End if
  1482.         else if (FLPEdge1[i].x<FLPEdge2[i].x)
  1483.           {
  1484.             FLPEdgeTable->Edge1 = FLPEdge2;
  1485.             FLPEdgeTable->Edge2 = FLPEdge1;
  1486.             break;
  1487.           } // End if
  1488.       } // End if
  1489.   } // End of CreateFLPEdgeTable for G3DDRAW
  1490.  
  1491. LONG Vx1,Vy1,Vx2,Vy2;
  1492.  
  1493. VOID G3DDRAW::XYIntersect ( FXPPOINT2D *In, FXPPOINT2D *Out,
  1494.                             FXPPOINT2D *Intersect, LONG Code, LONG ShadeFlags,
  1495.                             LONG FaceFlags )
  1496.   {    
  1497.     LONG LRatio;
  1498.     LONG Vx;
  1499.     LONG Ix,Iy,Ox,Oy;
  1500.     Ix = In->x;
  1501.     Iy = In->y;
  1502.     Ox = Out->x;
  1503.     Oy = Out->y;
  1504.  
  1505.     switch (Code)
  1506.       {
  1507.         case CLIP_TOP :
  1508.           LRatio = ((Vy1-Oy)<<16)/(Iy-Oy);
  1509.           Intersect->x = (LONG)(FXPMult((Ix-Ox),LRatio)+Ox);
  1510.           Intersect->y = Vy1;
  1511.           break;
  1512.         case CLIP_LEFT :
  1513.           Vx = Vx1 << 16;
  1514.           LRatio = (LONG)FXPDiv((Vx-Ox),(Ix-Ox));
  1515.           Intersect->x = Vx;
  1516.           Intersect->y = (((Iy-Oy)*LRatio)>>16)+Oy;
  1517.           break;
  1518.         case CLIP_BOTTOM :
  1519.           LRatio = ((Vy2-Oy)<<16)/(Iy-Oy);
  1520.           Intersect->x = (LONG)(FXPMult((Ix-Ox),LRatio)+Ox);
  1521.           Intersect->y = Vy2;
  1522.           break;
  1523.         case CLIP_RIGHT :
  1524.           Vx = Vx2 << 16;
  1525.           LRatio = (LONG)FXPDiv((Vx-Ox),(Ix-Ox));
  1526.           Intersect->x = Vx;
  1527.           Intersect->y = (((Iy-Oy)*LRatio)>>16)+Oy;
  1528.           break;
  1529.       } // End switch
  1530.  
  1531.     if (ShadeFlags==SHADE_GOURAUD)
  1532.       {}
  1533.     if (FaceFlags==FACE_TEXTURE)
  1534.       {}
  1535.   } // End of XYIntersect for G3DDRAW
  1536.  
  1537. LONG G3DDRAW::ClipFXPPolygon ( FXPPOINT2D *Points, LONG NumPoints, LONG Code, 
  1538.                                LONG ShadeFlags, LONG FaceFlags )
  1539.   {
  1540.     FXPPOINT2D *P1,*P2;
  1541.     FXPPOINT2D *LastPoint;
  1542.     FXPPOINT2D *ClipPolyPtr;
  1543.     FXPPOINT2D *SrcPoly;
  1544.     LONG NewNumPoints;
  1545.     LONG x1,y1,x2,y2;
  1546.  
  1547.     if (Code==0)  // No Clipping is necessary
  1548.       {
  1549.         ClipPoly = Points;
  1550.         return NumPoints;
  1551.       } // End if
  1552.  
  1553.     x1 = Vx1 << 16;
  1554.     x2 = Vx2 << 16;
  1555.     y1 = Vy1;
  1556.     y2 = Vy2;
  1557.  
  1558.     SrcPoly = Points;
  1559.  
  1560.     // Clip for Top
  1561.     if (Code&CLIP_TOP)
  1562.       {
  1563.         NewNumPoints = 0;
  1564.         ClipPolyPtr = TopClipPoly;
  1565.         P1 = LastPoint = &(SrcPoly[NumPoints-1]);  // Get the last one
  1566.         P2 = SrcPoly;
  1567.  
  1568.         do
  1569.           {
  1570.             if (P1->y>=y1) // If P1 is Inside
  1571.               {
  1572.                 if (P2->y>=y1)  // If P2 is Inside
  1573.                   {
  1574.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1575.                     NewNumPoints++;
  1576.                   } // End if
  1577.                 else
  1578.                   {
  1579.                     // Add Intersection
  1580.                     XYIntersect ( P1, P2, ClipPolyPtr++, CLIP_TOP,
  1581.                                   ShadeFlags, FaceFlags );
  1582.                     NewNumPoints++;
  1583.                   } // End else
  1584.                } // End if
  1585.             else // If P1 is outside
  1586.               {
  1587.                 if (P2->y>=y1)  // If P2 is Inside
  1588.                   {
  1589.                     // Add Intersection
  1590.                     XYIntersect ( P2, P1, ClipPolyPtr++, CLIP_TOP,
  1591.                                   ShadeFlags, FaceFlags );
  1592.                     NewNumPoints++;
  1593.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1594.                     NewNumPoints++;
  1595.                   } // End if
  1596.               } // End else
  1597.             P1 = P2;
  1598.           } while (P2++<LastPoint); // End while
  1599.         SrcPoly = TopClipPoly;
  1600.         NumPoints = NewNumPoints;
  1601.       } // End if
  1602.  
  1603.     if (NumPoints<3)
  1604.       return NumPoints;
  1605.  
  1606.     // Clip for Left
  1607.     if (Code&CLIP_LEFT)
  1608.       {
  1609.         NewNumPoints = 0;
  1610.         ClipPolyPtr = LeftClipPoly;
  1611.         P1 = LastPoint = &(SrcPoly[NumPoints-1]);  // Get the last one
  1612.         P2 = SrcPoly;
  1613.  
  1614.         do
  1615.           {
  1616.             if (P1->x>=x1) // If P1 is Inside
  1617.               {
  1618.                 if (P2->x>=x1)  // If P2 is Inside
  1619.                   {
  1620.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1621.                     NewNumPoints++;
  1622.                   } // End if
  1623.                 else
  1624.                   {
  1625.                     // Add Intersection
  1626.                     XYIntersect ( P1, P2, ClipPolyPtr++, CLIP_LEFT,
  1627.                                   ShadeFlags, FaceFlags );
  1628.                     NewNumPoints++;
  1629.                   } // End else
  1630.                } // End if
  1631.             else // If P1 is outside
  1632.               {
  1633.                 if (P2->x>=x1)  // If P2 is Inside
  1634.                   {
  1635.                     // Add Intersection
  1636.                     XYIntersect ( P2, P1, ClipPolyPtr++, CLIP_LEFT,
  1637.                                   ShadeFlags, FaceFlags );
  1638.                     NewNumPoints++;
  1639.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1640.                     NewNumPoints++;
  1641.                   } // End if
  1642.               } // End else
  1643.             P1 = P2;
  1644.           } while (P2++<LastPoint); // End while
  1645.         SrcPoly = LeftClipPoly;
  1646.         NumPoints = NewNumPoints;
  1647.       } // End if
  1648.  
  1649.     if (NumPoints<3)
  1650.       return NumPoints;
  1651.  
  1652.     // Clip for Bottom
  1653.     if (Code&CLIP_BOTTOM)
  1654.       {
  1655.         NewNumPoints = 0;
  1656.         ClipPolyPtr = BottomClipPoly;
  1657.         P1 = LastPoint = &(SrcPoly[NumPoints-1]);  // Get the last one
  1658.         P2 = SrcPoly;
  1659.  
  1660.         do
  1661.           {
  1662.             if (P1->y<=y2) // If P1 is Inside
  1663.               {
  1664.                 if (P2->y<=y2)  // If P2 is Inside
  1665.                   {
  1666.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1667.                     NewNumPoints++;
  1668.                   } // End if
  1669.                 else
  1670.                   {
  1671.                     // Add Intersection
  1672.                     XYIntersect ( P1, P2, ClipPolyPtr++, CLIP_BOTTOM,
  1673.                                   ShadeFlags, FaceFlags );
  1674.                     NewNumPoints++;
  1675.                   } // End else
  1676.                } // End if
  1677.             else // If P1 is outside
  1678.               {
  1679.                 if (P2->x<=y2)  // If P2 is Inside
  1680.                   {
  1681.                     // Add Intersection
  1682.                     XYIntersect ( P2, P1, ClipPolyPtr++, CLIP_BOTTOM,
  1683.                                   ShadeFlags, FaceFlags );
  1684.                     NewNumPoints++;
  1685.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1686.                     NewNumPoints++;
  1687.                   } // End if
  1688.               } // End else
  1689.             P1 = P2;
  1690.           } while (P2++<LastPoint); // End while
  1691.         SrcPoly = BottomClipPoly;
  1692.         NumPoints = NewNumPoints;
  1693.       } // End if
  1694.  
  1695.     if (NumPoints<3)
  1696.       return NumPoints;
  1697.  
  1698.     // Clip for Right
  1699.     if (Code&CLIP_RIGHT)
  1700.       {
  1701.         NewNumPoints = 0;
  1702.         ClipPolyPtr = RightClipPoly;
  1703.         P1 = LastPoint = &(SrcPoly[NumPoints-1]);  // Get the last one
  1704.         P2 = SrcPoly;
  1705.  
  1706.         do
  1707.           {
  1708.             if (P1->x<=x2) // If P1 is Inside
  1709.               {
  1710.                 if (P2->x<=x2)  // If P2 is Inside
  1711.                   {
  1712.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1713.                     NewNumPoints++;
  1714.                   } // End if
  1715.                 else
  1716.                   {
  1717.                     // Add Intersection
  1718.                     XYIntersect ( P1, P2, ClipPolyPtr++, CLIP_RIGHT,
  1719.                                   ShadeFlags, FaceFlags );
  1720.                     NewNumPoints++;
  1721.                   } // End else
  1722.                } // End if
  1723.             else // If P1 is outside
  1724.               {
  1725.                 if (P2->x<=x2)  // If P2 is Inside
  1726.                   {
  1727.                     // Add Intersection
  1728.                     XYIntersect ( P2, P1, ClipPolyPtr++, CLIP_RIGHT,
  1729.                                   ShadeFlags, FaceFlags );
  1730.                     NewNumPoints++;
  1731.                     *(ClipPolyPtr++) = *P2;  // Add this Point
  1732.                     NewNumPoints++;
  1733.                   } // End if
  1734.               } // End else
  1735.             P1 = P2;
  1736.           } while (P2++<LastPoint); // End while
  1737.         SrcPoly = RightClipPoly;
  1738.         NumPoints = NewNumPoints;
  1739.       } // End if
  1740.  
  1741.     ClipPoly = SrcPoly;
  1742.     return NumPoints;
  1743.   } // End of ClipFXPPolygon for G3DDRAW
  1744.  
  1745. ScanEdgeType ScanEdgeFunction;
  1746. DrawPolyType DrawPolyFunction;
  1747.  
  1748. BOOLEAN G3DDRAW::CreateFXPEdgeTable ( FXPPOINT2D *Points, LONG NumPoints,
  1749.                                       LONG ShadeFlags, LONG FaceFlags )
  1750.   {
  1751.     LONG i;
  1752.     LONG TopY,BottomY;
  1753.     LONG LeftX,RightX;
  1754.     FXPPOINT2D *PointPtr;
  1755.     FXPPOINT2D *TopPointPtr;
  1756.  
  1757.     PointPtr = Points;
  1758.  
  1759.     FXPPOINT2D *FirstPtr,*LastPtr;
  1760.     FirstPtr = TopPointPtr = Points;
  1761.     LastPtr = &(Points[NumPoints-1]);
  1762.  
  1763.     TopY = BottomY = TopPointPtr->y;
  1764.     LeftX = RightX = TopPointPtr->x;
  1765.  
  1766.     PointPtr++;
  1767.  
  1768.     LONG x,y;
  1769.     do
  1770.       {
  1771.         x = PointPtr->x;
  1772.         y = PointPtr->y;
  1773.  
  1774.         if (x<LeftX)
  1775.           {
  1776.             LeftX = x;
  1777.           } // End if
  1778.         else if (x>RightX)
  1779.           {
  1780.             RightX = x;
  1781.           } // End else if
  1782.  
  1783.         if (y<TopY)
  1784.           {
  1785.             TopPointPtr = PointPtr;
  1786.             TopY = y;
  1787.           } // End if
  1788.         else if (y>BottomY)
  1789.           {
  1790.             BottomY = y;
  1791.           } // End else if
  1792.       } while (PointPtr++<LastPtr); // End while
  1793.  
  1794.     LONG ClipCode=0;
  1795.  
  1796.     LeftX >>= 16;
  1797.     RightX >>= 16;
  1798.  
  1799.     if (RightX<ViewPort.x1)
  1800.       return FALSE;
  1801.     if (LeftX>ViewPort.x2)
  1802.       return FALSE;
  1803.     if (BottomY<ViewPort.y1)
  1804.       return FALSE;
  1805.     if (TopY>ViewPort.y2)
  1806.       return FALSE;
  1807.  
  1808.     if (LeftX<ViewPort.x1)
  1809.       ClipCode |= CLIP_LEFT;
  1810.     if (RightX>ViewPort.x2)
  1811.       ClipCode |= CLIP_RIGHT;
  1812.     if (TopY<ViewPort.y1)
  1813.       ClipCode |= CLIP_TOP;
  1814.     if (BottomY>ViewPort.y2)
  1815.       ClipCode |= CLIP_BOTTOM;
  1816.  
  1817.     NumPoints = ClipFXPPolygon ( Points, NumPoints, ClipCode,
  1818.                                  ShadeFlags, FaceFlags );
  1819.     if (NumPoints<3)
  1820.       return FALSE;
  1821.     if (ClipPoly!=Points)  // If clipped, Do it again
  1822.       {
  1823.         PointPtr = ClipPoly;
  1824.         FirstPtr = TopPointPtr = ClipPoly;
  1825.         LastPtr = &(ClipPoly[NumPoints-1]);
  1826.  
  1827.         TopY = BottomY = PointPtr->y;
  1828.         PointPtr++;
  1829.         do
  1830.           {
  1831.             y = PointPtr->y;
  1832.             if (y<TopY)
  1833.               {
  1834.                 TopPointPtr = PointPtr;
  1835.                 TopY = y;
  1836.               } // End if
  1837.             else if (y>BottomY)
  1838.               {
  1839.                 BottomY = y;
  1840.               } // End else if
  1841.           } while (PointPtr++<LastPtr); // End while
  1842.       } // End if
  1843.  
  1844.     if (BottomY==TopY)
  1845.       return FALSE;
  1846.  
  1847.     FXPEdgeTable.Start = TopY;
  1848.     FXPEdgeTable.Length = (LONG)(BottomY-TopY)+1;
  1849.  
  1850.     FXPPOINT2D *NextPtr;
  1851.     FXPPOINT2D **PointPtrPtr;
  1852.  
  1853.     // Sort Increase side
  1854.     NumEdge1 = 0;
  1855.     NextPtr = TopPointPtr;
  1856.     y = TopY;
  1857.     PointPtrPtr = FXPEdge1Index;
  1858.  
  1859.     while (y<BottomY)
  1860.       {
  1861.         PointPtr = NextPtr;
  1862.         if (NextPtr<LastPtr)
  1863.           NextPtr++;
  1864.         else
  1865.           NextPtr = FirstPtr;
  1866.         if ((y!=TopY)||(NextPtr->y!=TopY))
  1867.           {
  1868.             *(PointPtrPtr++) = PointPtr;
  1869.             y = PointPtr->y;
  1870.             NumEdge1++;
  1871.           } // End if
  1872.       } // End if
  1873.  
  1874.     // Sort Decrease side
  1875.     NumEdge2 = 0;
  1876.     NextPtr = TopPointPtr;
  1877.     y = TopY;
  1878.     PointPtrPtr = FXPEdge2Index;
  1879.  
  1880.     while (y<BottomY)
  1881.       {
  1882.         PointPtr = NextPtr;
  1883.         if (NextPtr>FirstPtr)
  1884.           NextPtr--;
  1885.         else
  1886.           NextPtr = LastPtr;
  1887.         if ((y!=TopY)||(NextPtr->y!=TopY))
  1888.           {
  1889.             *(PointPtrPtr++) = PointPtr;
  1890.             y = PointPtr->y;
  1891.             NumEdge2++;
  1892.           } // End if
  1893.       } // End if
  1894.  
  1895.     FXPEDGE *EdgePtr;
  1896.  
  1897.     FXPPOINT2D **IndexPtr1;
  1898.     FXPPOINT2D **IndexPtr2;
  1899.  
  1900.     // Create Edge1 table
  1901.     EdgePtr = FXPEdge1;
  1902.     IndexPtr1 = FXPEdge1Index;
  1903.     IndexPtr2 = IndexPtr1;
  1904.     IndexPtr2++;
  1905.     i = NumEdge1-2;
  1906.     while (i--)
  1907.       {
  1908.         EdgePtr = ScanEdgeFunction ( *(IndexPtr1++), *(IndexPtr2++),
  1909.                                      EdgePtr, 0 );
  1910.       } // End while
  1911.     ScanEdgeFunction ( *IndexPtr1, *IndexPtr2,
  1912.                        EdgePtr, 1 );
  1913.  
  1914.     // Create Edge2 table
  1915.     EdgePtr = FXPEdge2;
  1916.     IndexPtr1 = FXPEdge2Index;
  1917.     IndexPtr2 = IndexPtr1;
  1918.     IndexPtr2++;
  1919.     i = NumEdge2-2;
  1920.     while (i--)
  1921.       {
  1922.         EdgePtr = ScanEdgeFunction ( *(IndexPtr1++), *(IndexPtr2++),
  1923.                                      EdgePtr, 0 );
  1924.       } // End while
  1925.     ScanEdgeFunction ( *IndexPtr1, *IndexPtr2,
  1926.                        EdgePtr, 1 );
  1927.  
  1928.     // Compare which one is the left and right
  1929.     FXPEDGE *Edge1Ptr,*Edge2Ptr;
  1930.     FXPEdgeTable.Edge1 = Edge1Ptr = FXPEdge1;
  1931.     FXPEdgeTable.Edge2 = Edge2Ptr = FXPEdge2;
  1932.  
  1933.     LONG x1,x2;
  1934.  
  1935.     i = FXPEdgeTable.Length;
  1936.     do
  1937.       {
  1938.         x1 = Edge1Ptr->x;
  1939.         x2 = Edge2Ptr->x;
  1940.         Edge1Ptr++;
  1941.         Edge2Ptr++;
  1942.         if (x1<x2)
  1943.           {
  1944.             break;
  1945.           } // End if
  1946.         else if (x1>x2)
  1947.           {
  1948.             FXPEdgeTable.Edge1 = FXPEdge2;
  1949.             FXPEdgeTable.Edge2 = FXPEdge1;
  1950.             break;
  1951.           } // End if
  1952.       } while (i--); // End if
  1953.  
  1954.     return TRUE;
  1955.   } // End of CreateFXPEdgeTable for G3DDRAW
  1956.  
  1957. VOID G3DDRAW::CreateFXPGradient ( FXPGRADIENT *FXPGradient, FXPPOINT2D *Points, LONG ShadeFlags,
  1958.                                   LONG FaceFlags )
  1959.   {
  1960.     if ((ShadeFlags==0)&&(FaceFlags==0))
  1961.       return;
  1962.  
  1963.     float x0,x1,x2;
  1964.     float y0,y1,y2;
  1965.  
  1966.     x0 = (float)(Points[0].x>>16);
  1967.     y0 = (float)(Points[0].y);
  1968.     x1 = (float)(Points[1].x>>16);
  1969.     y1 = (float)(Points[1].y);
  1970.     x2 = (float)(Points[2].x>>16);
  1971.     y2 = (float)(Points[2].y);
  1972.  
  1973.     float dX,OneOverdX,OneOverdY;
  1974.     dX = (x1-x2)*(y0-y2) - (x0-x2)*(y1-y2);
  1975.     if (dX==0)
  1976.       {
  1977.         FXPGradient->OneOverZdX = 0; FXPGradient->OneOverZdY = 0;
  1978.         FXPGradient->UOverZdX = 0; FXPGradient->UOverZdY = 0;
  1979.         FXPGradient->VOverZdX = 0; FXPGradient->VOverZdY = 0;
  1980.         FXPGradient->IOverZdX = 0; FXPGradient->IOverZdY = 0;
  1981.         FXPGradient->HOverZdX = 0; FXPGradient->HOverZdY = 0;
  1982.       } // End if
  1983.  
  1984.     OneOverdX = (float)1 / dX;
  1985.     OneOverdY = -OneOverdX;
  1986.  
  1987.     if (ShadeFlags==SHADE_GOURAUD)
  1988.       {
  1989.         float I0,I1,I2;
  1990.         I0 = (float)(Points[0].I);  // I is 16:16
  1991.         I1 = (float)(Points[1].I);
  1992.         I2 = (float)(Points[2].I);
  1993.         float IOverZdX,IOverZdY;
  1994.  
  1995.         IOverZdX = ((I1-I2)*(y0-y2)-(I0-I2)*(y1-y2)) * OneOverdX;
  1996.         IOverZdY = ((I1-I2)*(x0-x2)-(I0-I2)*(x1-x2)) * OneOverdY;
  1997.  
  1998.         FXPGradient->IOverZdX = (LONG)IOverZdX;
  1999.         FXPGradient->IOverZdY = (LONG)IOverZdY;
  2000.       } // End if
  2001.     if (FaceFlags==FACE_TEXTURE)
  2002.       {
  2003.         float U0,U1,U2;
  2004.         float V0,V1,V2;
  2005.         U0 = (float)(Points[0].u);  // U is 16:16
  2006.         V0 = (float)(Points[0].v);  // V is 16:16
  2007.         U1 = (float)(Points[1].u);  // V is 16:16
  2008.         V1 = (float)(Points[1].v);  // U is 16:16
  2009.         U2 = (float)(Points[2].u);  // V is 16:16
  2010.         V2 = (float)(Points[2].v);  // U is 16:16
  2011.         float UOverZdX,UOverZdY;
  2012.         float VOverZdX,VOverZdY;
  2013.  
  2014.         UOverZdX = ((U1-U2)*(y0-y2)-(U0-U2)*(y1-y2)) * OneOverdX;
  2015.         UOverZdY = ((U1-U2)*(x0-x2)-(U0-U2)*(x1-x2)) * OneOverdY;
  2016.         VOverZdX = ((V1-V2)*(y0-y2)-(V0-V2)*(y1-y2)) * OneOverdX;
  2017.         VOverZdY = ((V1-V2)*(x0-x2)-(V0-V2)*(x1-x2)) * OneOverdY;
  2018.  
  2019.         FXPGradient->UOverZdX = (LONG)UOverZdX;
  2020.         FXPGradient->UOverZdY = (LONG)UOverZdY;
  2021.         FXPGradient->VOverZdX = (LONG)VOverZdX;
  2022.         FXPGradient->VOverZdY = (LONG)VOverZdY;
  2023.       } // End if
  2024.  
  2025.     #if defined (__FORWATCOM__)
  2026.       _SetGradientData ( FXPGradient );
  2027.     #endif
  2028.   } // End of CreateFXPGradient for G3DDRAW
  2029.  
  2030. VOID G3DDRAW::DrawPolySlow ( FXPPOINT2D *Points, ANIMIMAGE *Texture,
  2031.                              LONG Intensity, LONG Color, LONG DrawShadeFlags,
  2032.                              LONG DrawFaceFlags )
  2033.   {
  2034.     if (Texture)
  2035.       {}
  2036.     if (Intensity)
  2037.       {}
  2038.  
  2039.     Vx1 = ViewPort.x1;
  2040.     Vy1 = ViewPort.y1;
  2041.     Vx2 = ViewPort.x2;
  2042.     Vy2 = ViewPort.y2;
  2043.  
  2044.     ScanEdgeFunction = DrawRoutine[DrawShadeFlags][DrawFaceFlags][FALSE][FALSE].ScanEdgePtr;
  2045.     DrawPolyFunction = DrawRoutine[DrawShadeFlags][DrawFaceFlags][FALSE][FALSE].DrawPolyPtr;
  2046.  
  2047.     FXPGRADIENT FXPGradient;
  2048.     CreateFXPGradient ( &FXPGradient, Points, DrawShadeFlags, DrawFaceFlags );
  2049.  
  2050.     if (CreateFXPEdgeTable ( Points, 3, DrawShadeFlags, DrawFaceFlags )==FALSE)
  2051.       return;
  2052.  
  2053.     FXPEDGE *LeftEdge = FXPEdgeTable.Edge1;
  2054.     FXPEDGE *RightEdge = FXPEdgeTable.Edge2;
  2055.  
  2056.     BYTE *DestBuffer = Dest->SetOffset ( 0, FXPEdgeTable.Start );
  2057.     LONG AddDest = Dest->GetRowInc ();
  2058.  
  2059.     #if defined (__FORWATCOM__)
  2060.       _SetDestData ( DestBuffer, AddDest );
  2061.       _SetEdgeData ( LeftEdge, RightEdge, sizeof(FXPEDGE) );
  2062.     #else
  2063.       if (LeftEdge)
  2064.         {}
  2065.       if (RightEdge)
  2066.         {}
  2067.     #endif
  2068.     DrawPolyFunction ( Color, 0, 0, FXPEdgeTable.Length );
  2069.   } // End of DrawTriangle for G3DDRAW
  2070.  
  2071. VOID G3DDRAW::TestDrawTriangle2 ( FXPPOINT2D *Points, ANIMIMAGE *Texture,
  2072.                                   LONG Intensity, LONG Color, LONG DrawShadeFlags,
  2073.                                   LONG DrawFaceFlags, COLORTABLE *BlendTBL, COLORTABLE *ShadeTBL,
  2074.                                   COLORTABLE *HazeTBL )
  2075.   {
  2076.     ShadeTable = ShadeTBL;
  2077.     HazeTable = HazeTBL;
  2078.     if (BlendTBL!=NULL)
  2079.       _BlendBuffer = BlendTBL->GetTable ();
  2080.     else
  2081.       _BlendBuffer = NULL;
  2082.  
  2083.     #if defined (__FORWATCOM__)
  2084.       _SetShadeTable ( ShadeTable->GetTable() );
  2085.       _SetTextureBuffer ( Texture->GetBuffer () );
  2086.     #endif
  2087.     DrawPolySlow ( Points, Texture, Intensity, Color, DrawShadeFlags, DrawFaceFlags );
  2088.   } // End of TestDrawTriangle for G3DDRAW                                 
  2089.   
  2090.